package ai_util;

import java.util.*;

public class RepetitionHashTable {
	public RepetitionHashTable(int size_in_bits) {
	}

	/**
	 * Call this to setup a new repetition set in the table
	 */
	public void increaseAge() {
		hash_current_age = (hash_current_age + 1) % hash_age_table.length;
		if (hash_current_age == 0) {
			Arrays.fill(hash_table, 0);
			hash_current_age++;
		}
		//LogFile.message("age "+hash_current_age);
	}

	// Hash table for storing repeated positions
	private static long hash_mask = 0xFFFFF;
	private static long hash_table[] = new long[65536 * 16];
	private static long hash_age_table[] = new long[256];
	public static int hash_current_age = 0;
	static {
		Random random = new Random(123456);
		for (int i = 0; i < hash_age_table.length; i++) {
			hash_age_table[i] = random.nextLong();
		}
	}

	/**
	 * Tests if given hash_code is already in the hash table Stores given hash
	 * code in the hash table
	 * 
	 * @param hash_code
	 *            long
	 * @return boolean
	 */

	public boolean isRepetition(long hash_code) {
		// Need to use all 64 bits of hash to spread the indicies
		int index = (int) (hash_code % (hash_mask - 7));
		if (index < 0) {
			index += hash_mask;
		}
		long age_mask = 0xFF;
		long target = (hash_code & ~age_mask) | hash_current_age;
		while (hash_current_age == (hash_table[index] & age_mask)) {
			if (target == hash_table[index]) {
				return true;
			}
			index = (index + 1) % (int) hash_mask;
		}

		hash_table[index] = target;
		return false;
	}
	
	public static void main(String args[]) {
		Long Tests[] = {-3741314856828041826L, -5671695027107892188L, -5369513543504626476L, -3037346619180571682L, 
				-2007902825895846730L, -500362090423014876L, -8777629142385800289L, -2380889690315494815L,
				7343050807652738242L, 3372543960146856813L, 2081258436976912999L, 1191091397295401954L,
				985090951932992880L, -2380889690315494815L};
		RepetitionHashTable repetition = new RepetitionHashTable(19);
		repetition.increaseAge();
		for (Long test : Tests) {
			if (repetition.isRepetition(test)) {
				LogFile.message(""+test+" is repetition");
			} else
			{
				LogFile.message(""+test+" is not repetition");
			}
		}
	}
}
